package edu.cdnu.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import edu.cdnu.common.constant.MessageConstatnt;
import edu.cdnu.common.dto.CourseManageDto;
import edu.cdnu.common.dto.DepartmentAndTeacherDto;
import edu.cdnu.common.request.CourseManageRequest;
import edu.cdnu.common.result.ResultEntity;
import edu.cdnu.pojo.CourseClassPojo;
import edu.cdnu.pojo.CoursePojo;
import edu.cdnu.pojo.CourseStudentPojo;
import edu.cdnu.pojo.CourseTeacherPojo;
import edu.cdnu.pojo.DictionaryPojo;
import edu.cdnu.pojo.TeacherPojo;
import edu.cdnu.service.CommonService;
import edu.cdnu.service.CourseService;
import edu.cdnu.service.StudentService;
import edu.cdnu.service.TeacherService;
/**
 * 关于课程操作的Controller层
 * @author ASUS AsingZ
 */
@RestController
@RequestMapping("/course")
public class CourseController {
	
	@Autowired
	private CourseService courseService;
	@Autowired
	private TeacherService teacherService;
	@Autowired
	private StudentService studentService;
	@Autowired
	private CommonService commonService;
	// 事务管理器，手动实现事务的时候使用
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	@Autowired
	private TransactionDefinition transactionDefinition;

	/**
	 * 展示的所有课程的信息，以及课程所包含的一些信息
	 * @return
	 */
	@GetMapping("/courseManageList")
	public ResultEntity<List<CourseManageDto>> selectAllCourseManageList(){
		List<CourseManageDto> coursePojoList = new ArrayList<>();
		// 课程表的信息list
		List<CoursePojo> list=courseService.selectCourseListByCourseId(null);
		list.forEach((item)->{
			CourseManageDto c=new CourseManageDto(item.getId(), item.getName(), item.getDescription(), item.getSyllabus());
			coursePojoList.add(c);
		});
		// 遍历课程把对应关系查出来
		coursePojoList.forEach((item)->{
			// 1.课程--教师
			List<CourseTeacherPojo> ctList=courseService.selectCourseTeacherRelationshipListByCourseId(item.getId());
			// 2.课程--班级
			List<CourseClassPojo> ccList=courseService.selectCourseClassRelationshipListByCourseId(item.getId());
			// 3.课程--学员
			List<CourseStudentPojo> csList=courseService.selectCourseStudentRelationshipListByCourseId(item.getId());
			// 关系的list  set进去
			item.setRelationshipList(ctList, csList, ccList);
			
			// 循环对应关系，把详细的对象也查询出来
			// 1.课程--教师
			// 保存了一众教师的id
			List<Integer> teacherIdList=ctList.stream().map(ctItem->{
				return ctItem.getTeacherId();
			}).collect(Collectors.toList());
			// 教师对象数据 set进去
			item.setTeacherList(teacherService.selectTeacherListByIdList(teacherIdList));
			
			// 2.课程--班级  班级那些存在数据字典表里面
			// 这个后面再由前端查询吧
			
			// 3.课程--学员
			// 保存了一众学员的id
			List<Integer> studentIdList=csList.stream().map(csItem->{
				return csItem.getStudentId();
			}).collect(Collectors.toList());
			// 学生对象数据 set进去
			item.setStudentList(studentService.selectStudentListByIdList(studentIdList));
		});
		
		return ResultEntity.createSuccessResult(coursePojoList);
	}
	
	/**
	 * 修改课程的基础信息
	 * @param coursePojo
	 * @return
	 */
	@PostMapping("/updateCourse")
	public ResultEntity<?> updateCourseBaseInfo(@RequestBody CoursePojo coursePojo){
		courseService.updateCourseByCourseId(coursePojo);
		return ResultEntity.createSuccessResult(null);
	}
	
	/**
	 * 学院列表，学院下有所属这个学院的教师列表
	 * @return
	 */
	@GetMapping("/departmentTeacherList")
	public ResultEntity<List<DepartmentAndTeacherDto>> selectDepartmentAndTeacherList(){
		List<DepartmentAndTeacherDto> list=new ArrayList<>();
		List<TeacherPojo> teacherList=teacherService.selectTeacherListByRoleId(null);
		commonService.selectAllDepartmentList().forEach((item)->{
			list.add(
					new DepartmentAndTeacherDto(item.getId(),item.getName(),item.getParentId(),item.getDecription()
						,teacherList.stream().filter((teacherItem)->{
							return teacherItem.getDepartmentId() != null && teacherItem.getDepartmentId() == item.getId();
						}).collect(Collectors.toList())
					)
				) ;
		});;
		
		return ResultEntity.createSuccessResult(list);
	}
	
	@Transactional
	@PostMapping("/addOrUpdateCourse")
	public ResultEntity<?> addOrUpdateCourseInfo(@RequestBody CourseManageRequest courseReq){
		if(courseReq.getId()==null) {
			// 新增
			// 1.基础信息
			int courseId=courseService.insertCourseReturnId(new CoursePojo(courseReq.getName(), courseReq.getDescription(), courseReq.getSyllabus()));
			// 2. 教师对应关系
			List<CourseTeacherPojo> courseTeacherList=new ArrayList<>();
			courseReq.getChooseTeacherList().forEach(item->{
				courseTeacherList.add(new CourseTeacherPojo(item.get(1), courseId));
			});
			courseService.insertCourseTeacherByList(courseTeacherList);
			// 3.班级对应关系
			List<CourseClassPojo> courseClassList=new ArrayList<>();
			courseReq.getChooseClassList().forEach(item->{
				// [departmentId,subjectId,classId]
				courseClassList.add(new CourseClassPojo(courseId, item.get(0), item.get(1), item.get(2)));
			});
			courseService.insertCourseClassByList(courseClassList);
			
		}else {
			// 修改
			
			// 存放请求没有，数据库有的（要删除的）
			List<Integer> deleteList=new ArrayList<>();
			// 存放请求有，数据库没有的(要加的)
			List<Integer> addList=new ArrayList<>();
			
			// 1.直接修改基础信息
			//courseService.updateCourseByCourseId(new CoursePojo(courseReq.getId(), courseReq.getName(), courseReq.getDescription(), courseReq.getSyllabus()));
			// 2.判断教师改变了哪些
			
			// 保存数据库有的教师列表
			List<Integer> teacherMysqlList=courseService.selectTeacherIdListByCourseId(courseReq.getId());
			// 保存请求的教师列表
			List<Integer> teacherReqList=new ArrayList<>();
			
			// 循环改变后的list,
			courseReq.getChooseTeacherList().forEach(list->{
				// 里面每一个list对应 [departmentId,teacherId] 取1（第2个）就是教师id
				teacherReqList.add(list.get(1));
			});
			// 排序
			Collections.sort(teacherReqList);
			
			int mIndex=0,rIndex=0;
			while(mIndex<teacherMysqlList.size() || rIndex<teacherReqList.size()) {
				// 先判断越界,两边都越界不会进来
				if(mIndex>=teacherMysqlList.size() && rIndex<teacherReqList.size()) {
					// 左边越界右边没越界 增
					addList.add(teacherReqList.get(rIndex));
					// 右边出
					rIndex++;
					break;
				}else if(mIndex<teacherMysqlList.size() && rIndex>=teacherReqList.size()){
					// 右边越界左边没越界 删
					deleteList.add(teacherMysqlList.get(mIndex));
					// 左边出
					mIndex++;
					break;
				}
				
				int left=teacherMysqlList.get(mIndex);
				int right=teacherReqList.get(rIndex);
				if(left<right) {
					// 数据库里面的小，删
					deleteList.add(left);
					// 左边出
					mIndex++;
				}else if(left==right) {
					// 相等不管，一起出
					mIndex++;
					rIndex++;
				}else if(left>right) {
					// 请求的数据小，增
					addList.add(right);
					// 右边出
					rIndex++;
				}
			}
			
			List<CourseTeacherPojo> ctList=new ArrayList<>();
			addList.forEach(item->{
				ctList.add(new CourseTeacherPojo(item,courseReq.getId()));
			});
			
			// 添加
			courseService.insertCourseTeacherByList(ctList);
			
			// 循环删除
			deleteList.forEach(item->{
				courseService.deleteCourseTeacherByCourseTeacherPojo(new CourseTeacherPojo(item,courseReq.getId()));
			});
			// 3.班级
		}
		return ResultEntity.createSuccessResult(null);
	}
	
	
	@GetMapping("/courseList/{teacherId}")
	public ResultEntity<List<CourseManageDto>> selectCourseManageListByTeacherId(@PathVariable String teacherId){
		List<CourseManageDto> coursePojoList = new ArrayList<>();
		// 装课程的id的list
		List<Integer> idList=courseService.selectCourseIdListByTeacherId(Integer.valueOf(teacherId));
		// 课程表的信息list
		List<CoursePojo> list=courseService.selectCourseListByCourseIdList(idList);
		list.forEach((item)->{
			CourseManageDto c=new CourseManageDto(item.getId(), item.getName(), item.getDescription(), item.getSyllabus());
			coursePojoList.add(c);
		});
		// 遍历课程把对应关系查出来
		coursePojoList.forEach((item)->{
			// 1.课程--教师
			List<CourseTeacherPojo> ctList=courseService.selectCourseTeacherRelationshipListByCourseId(item.getId());
			// 2.课程--班级
			List<CourseClassPojo> ccList=courseService.selectCourseClassRelationshipListByCourseId(item.getId());
			// 3.课程--学员
			List<CourseStudentPojo> csList=courseService.selectCourseStudentRelationshipListByCourseId(item.getId());
			// 关系的list  set进去
			item.setRelationshipList(ctList, csList, ccList);
			
			// 循环对应关系，把详细的对象也查询出来
			// 1.课程--教师
			// 保存了一众教师的id
			List<Integer> teacherIdList=ctList.stream().map(ctItem->{
				return ctItem.getTeacherId();
			}).collect(Collectors.toList());
			// 教师对象数据 set进去
			item.setTeacherList(teacherService.selectTeacherListByIdList(teacherIdList));
			
			// 2.课程--班级  班级那些存在数据字典表里面
			// 这个后面再由前端查询吧
			
			// 3.课程--学员
			// 保存了一众学员的id
			List<Integer> studentIdList=csList.stream().map(csItem->{
				return csItem.getStudentId();
			}).collect(Collectors.toList());
			// 学生对象数据 set进去
			item.setStudentList(studentService.selectStudentListByIdList(studentIdList));
		});
		
		return ResultEntity.createSuccessResult(coursePojoList);
	}
	
	
	@GetMapping("/courseItem/{courseId}")
	public ResultEntity<CourseManageDto> selectCourseManageItemByCourseId(@PathVariable String courseId){
		// 装课程的id的list
		CoursePojo course=courseService.selectCourseItemByCourseId(Integer.valueOf(courseId));
		CourseManageDto c=new CourseManageDto(course.getId(), course.getName(), course.getDescription(), course.getSyllabus());
		// 把对应关系查出来
		// 1.课程--教师
		List<CourseTeacherPojo> ctList=courseService.selectCourseTeacherRelationshipListByCourseId(c.getId());
		// 2.课程--班级
		List<CourseClassPojo> ccList=courseService.selectCourseClassRelationshipListByCourseId(c.getId());
		// 3.课程--学员
		List<CourseStudentPojo> csList=courseService.selectCourseStudentRelationshipListByCourseId(c.getId());
		// 关系的list  set进去
		c.setRelationshipList(ctList, csList, ccList);
		
		// 循环对应关系，把详细的对象也查询出来
		// 1.课程--教师
		// 保存了一众教师的id
		List<Integer> teacherIdList=ctList.stream().map(ctItem->{
			return ctItem.getTeacherId();
		}).collect(Collectors.toList());
		// 教师对象数据 set进去
		c.setTeacherList(teacherService.selectTeacherListByIdList(teacherIdList));
		
		// 2.课程--班级  班级那些存在数据字典表里面
		// 这个后面再由前端查询吧
		
		// 3.课程--学员
		// 保存了一众学员的id
		List<Integer> studentIdList=csList.stream().map(csItem->{
			return csItem.getStudentId();
		}).collect(Collectors.toList());
		// 学生对象数据 set进去
		c.setStudentList(studentService.selectStudentListByIdList(studentIdList));
		
		return ResultEntity.createSuccessResult(c);
	}
	
	
	/**
	 * 导入课程
	 * <p>如果数据有错就直接回滚事务，不会成功导入数据</p>
	 * @param courses 二维数组，第一维是每行，下面是这一行的每列
	 * @return
	 */
//	@Transactional //这里手动开启事务不用这个注解
	@PostMapping("/importCourse")
	public ResultEntity<?> importCourse(@RequestBody List<List<String>> courses) throws Exception{
		// 先判断长度
		if(courses.size()<1||courses.get(0).size()<1) {
			return ResultEntity.createFailResult(MessageConstatnt.PARAMETER_LACK);
		}
		//手动开启事务
		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
		
		// 这个变量用于判断是否成功,因为在Lambda表达式中不能直接修改变量，所以用list来替代才能修改
		List<Boolean> complete=new ArrayList<>();
		complete.add(true);
		// 循环外面这层是每行，里面的list就是每一条数据
		courses.forEach((list)->{
			// 1.创建课程
			CoursePojo course=new CoursePojo(list.get(0), list.get(1), list.get(2));
			// 创建好了课程还返回了课程的id
			int courseId=courseService.insertCourseReturnId(course);
			// 2.创建 课程-教师 对应关系
			// 判断授课教师是否存在 （第4位-3-，数组长度大于3；值不为空）
			if(list.size()>3 && list.get(3)!=null && !"".equals(list.get(3))) {
				// 可能有多个教师，以逗号分隔
				String[] teacherNames=list.get(3).split(",|，");
				// 这个变量用于存放关系列表等会一起插入
				List<CourseTeacherPojo> courseTeacherList=new ArrayList<>();
				// 遍历所有教师添加关系
				for(String teacherName:teacherNames) {
					// 教师存在，获取这个教师
					TeacherPojo teacherPojo=new TeacherPojo();
					teacherPojo.setName(teacherName);
					teacherPojo=teacherService.selectTeacher(teacherPojo);
					// 获取到这个教师不为空则存放到列表里面
					if(teacherPojo!=null && teacherPojo.getId()!=null) {
						CourseTeacherPojo courseTeacher=new CourseTeacherPojo(teacherPojo.getId(), courseId);
						courseTeacherList.add(courseTeacher);
					}
					// 找不到就是数据有错，就不进行下面的操作了
					else {
						complete.set(0, false);
						return;
					}
				}
				// 创建课程与教师的关系
				courseService.insertCourseTeacherByList(courseTeacherList);
			}
			// 3.创建 课程-班级 对应关系
			// 判断授课教师是否存在 （第5位-4-，数组长度大于4；值不为空）
			if(list.size()>4 && list.get(4)!=null && !"".equals(list.get(4))) {
				// 可能有多个班级，以逗号分隔
				String[] classNames=list.get(4).split(",|，");
				// 这个变量用于存放关系列表等会一起插入
				List<CourseClassPojo> courseClassList=new ArrayList<>();
				for(String className:classNames) {
					// 找到这个班级对象
					DictionaryPojo clazz=commonService.selectDictionary(new DictionaryPojo(null, className, null, null));
					// 判断获取到这个数据字典对象是否为空
					if(clazz!=null && clazz.getId()!=null) {
						// 查询到上面两级（学院、专业的的数据）
						// 专业 （班级的父id就是专业的id）
						DictionaryPojo subject=commonService.selectDictionary(new DictionaryPojo(clazz.getParentId(), null, null, null));
						// 学院 （同上原理）
						DictionaryPojo department=commonService.selectDictionary(new DictionaryPojo(subject.getParentId(), null, null, null));
						// 将对象放到列表中
						courseClassList.add(new CourseClassPojo(courseId, department.getId(), subject.getId(), clazz.getId()));
					}
					// 找不到就是数据有错，就不进行下面的操作了
					else {
						complete.set(0, false);
						return;
					}
				}
				// 创建 课程-班级对应关系
				courseService.insertCourseClassByList(courseClassList);
			}
		});
		// 判断是否完成
		if(complete.get(0)) {
			dataSourceTransactionManager.commit(transactionStatus);//提交
			return ResultEntity.createSuccessResult(null);
		}
		// 否则事务回滚
//		TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		dataSourceTransactionManager.rollback(transactionStatus);
		return ResultEntity.createFailResult(MessageConstatnt.SOME_PARAMETER_ERROR);
	}
	
	
}
